package com.jh.mms.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.jh.mms.dao.IHqlDao;

@SuppressWarnings("unchecked")
public class HqlDaoImpl<T, PK extends Serializable> extends HibernateDaoSupport implements IHqlDao<T, PK> {

	private Session session = null;
		
	public Session openSession(){
		// TODO Auto-generated method stub
		if (null == session) 
			session = this.getSession();
		return session;
	}
	
	public void closeSession(){
		// TODO Auto-generated method stub
		if (null != session) { 
			session.close();
		}
	}

	public boolean executeSQL(String hql, List<T> params){
		// TODO Auto-generated method stub
		boolean result = false;
		if (null != hql && !"".equals(hql.trim())){
			try {
				session = this.getSession();
				Query query = session.createQuery(hql);
				if (null != params) {
					for(int i = 0; i < params.size(); i++) {
						query.setParameter(i, params.get(i));
					}
				}
				result = query.executeUpdate() > 0;
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}
	
	private String formatSqlStr(String hql, List params) {
		if (null == params || params.size() == 0) return hql;
		for (int i = 0; i < params.size(); i++) 
			hql = hql.replaceFirst("\\?", String.valueOf(params.get(i)));
		return hql;
	}
	
	public List<String> executeBatch(List<String> hql, List<T> params){
		// TODO Auto-generated method stub
		List result = new ArrayList();
		if (null != hql && 0 < hql.size()) {
			for(int i = 0; i < hql.size(); i++) {
				String _sql = hql.get(i);
				List _par = (List)params.get(i);
				if (!this.executeSQL(_sql, _par))
					result.add(this.formatSqlStr(_sql, _par));
			}
		}
		return result;
	}
	
	public List<T> find(String hql){
		// TODO Auto-generated method stub
		List result = null;
		if (null != hql && !"".equals(hql.trim())) {
			try {
				session = this.getSession();
				Query query = session.createQuery(hql);
				result = query.list();
			} catch(Exception ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	public List<T> find(String hql, int pageRows, int pageIndex){
		// TODO Auto-generated method stub
		List result = null;
		if (null != hql && !"".equals(hql.trim())){
			try {
				session = this.getSession();
				Query query = session.createQuery(hql);
				if (pageRows > 0 && pageIndex > 0) {
					query.setMaxResults(pageRows);
					query.setFirstResult(pageRows * (pageIndex - 1));
				}
				result = query.list();	
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	public List<T> find(String hql, List<T> params) {
		// TODO Auto-generated method stub
		List result = null;
		if (null != hql && !"".equals(hql.trim())){
			try {
				session = this.getSession();
				Query query = session.createQuery(hql);
				if (null != params) {
					for(int i = 0; i < params.size(); i++) {
						query.setParameter(i, params.get(i));
					}
				}
				result = query.list();		
			} catch(Exception ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	public List<T> find(String hql, List<T> params, int pageRows, int pageIndex){
		// TODO Auto-generated method stub
		List result = null;
		if (null != hql && !"".equals(hql.trim())){
			try {
				session = this.getSession();
				Query query = session.createQuery(hql);
				if (null != params) {
					for(int i = 0; i < params.size(); i++) {
						query.setParameter(i, params.get(i));
					}
				}
				if (pageRows > 0 && pageIndex > 0) {
					query.setMaxResults(pageRows);
					query.setFirstResult(pageRows * (pageIndex - 1));
				}
				result = query.list();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}
	
	public boolean update(T entity){
		// TODO Auto-generated method stub
		boolean result = false;
		Transaction tx = null;
		try {
			if (null != entity) {
				session = this.getSession();
				session.update(entity);
				result = true;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return result;
	}

	public List<T> updateBatch(List<T> entity){
		// TODO Auto-generated method stub
		List result = new ArrayList();
		for(T obj:entity) {
			if (!this.update(obj))
				result.add(obj);
		}
		return result;
	}
	
	public boolean delete(T entity){
		// TODO Auto-generated method stub
		boolean result = false;
		Transaction tx = null;
		try {
			if (null != entity) {
				session = this.getSession();
				session.delete(entity);
				result = true;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return result;
	}
	
	public boolean save(T entity){
		// TODO Auto-generated method stub
		boolean result = false;
		try {
			if (null != entity) {
				session = this.getSession();
				session.save(entity);
				result = true;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return result;
	}

	public boolean saveOrUpdate(T entity){
		// TODO Auto-generated method stub
		boolean result = false;
		Transaction tx = null;
		try {
			if (null != entity) {
				session = this.getSession();
				session.saveOrUpdate(entity);
				result = true;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return result;
	}
	
	public List<T> find(Class<T> cls, T entity, String[] orders, int pageRows, int pageIndex){
		// TODO Auto-generated method stub
		try {
			if (null != cls) {
				session = this.getSession();
				Criteria criteria = session.createCriteria(cls);
				if (entity != null) {
					Example example = Example.create(entity);
					example.enableLike(MatchMode.ANYWHERE);
					example.excludeNone();
					example.excludeZeroes();
					example.ignoreCase();
					criteria.add(example);
				}
				if (pageRows > 0 && pageIndex > 0) {
					criteria.setMaxResults(pageRows);
					criteria.setFirstResult(pageRows * (pageIndex - 1));
				}
				if (orders != null) {
					for(String ord:orders) {
						criteria.addOrder(Order.desc(ord));
					}
				}
				return criteria.list();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	public T get(Class<T> cls, PK pk){
		// TODO Auto-generated method stub
		try {
			session = this.getSession();
			return (T)session.get(cls, pk);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	public int listCount(Class<T> cls, T entity){
		List list = this.find(cls, entity, null, 0, 0);
		return (null != list) ? list.size() : -1;
	}
	
	public int listCount(String hql){
		String tempSql=hql.toLowerCase();
		int index=tempSql.indexOf("from");
		String start="SELECT COUNT(*) ";
		tempSql=start+hql.substring(index,hql.length());		
		List list = this.find(tempSql);
		return (null != list) ? Integer.parseInt(list.get(0).toString()) : -1;
	}

	public int listCount(String hql, List<T> params){	
		String tempSql=hql.toLowerCase();
		int index=tempSql.indexOf("from");
		String start="SELECT COUNT(*) ";
		tempSql=start+hql.substring(index,hql.length());		
		List list = this.find(tempSql,params);
		return (null != list) ? Integer.parseInt(list.get(0).toString()) : -1;
	}
}
